package com.gitee.wsl.ext.list

import com.gitee.wsl.ext.collection.getByIndex


/**
 * Removes the element at [idx] by creating a new list without the element.
 */
fun <E> List<E>.removeAt(idx: Int) = toMutableList().apply { removeAt(idx) }.toList()

/**
 * Removes values from the list as determined by the [predicate].
 * Generate an index-based loop that doesn't use an [Iterator].
 */
inline fun <T> MutableList<T>.removeIfIndices(predicate: (T) -> Boolean) {
    var numDeleted = 0
    for (rawIndex in indices) {
        val index = rawIndex - numDeleted
        if (predicate(get(index))) {
            removeAt(index)
            numDeleted++
        }
    }
}

fun <E> MutableList<E>.removeIf(filter: (E) -> Boolean): Boolean {
    var removed = false

    val each = listIterator()
    while (each.hasNext()) {
        if (filter(each.next())) {
            each.remove()
            removed = true
        }
    }
    return removed
}


fun <T> MutableList<T>.removeRange(start: Int, end: Int) {
    for (i in (end - 1) downTo start) {
        removeAt(i)
    }
}

inline fun <T> MutableList<T>.removeFirstOrNull(predicate: (T) -> Boolean): T? {
    this.forEachIndexed { index, element ->
        if (predicate(element)) {
            return this.removeAt(index)
        }
    }
    return null
}

fun <T> MutableList<T>.removeAfterIndex(afterIndex: Int) {
    while (lastIndex > afterIndex) {
        removeLast()
    }
}


/**
 * Returns a new List with all occurrences of [element] removed.
 *
 * The comparison between the elements is done non strict '=='
 */
fun <E> List<E>.remove(element: E): List<E> = filter { it != element }

/**
 * Returns a new List with all occurrences of [element] removed.
 *
 * The comparison between the elements is done strict '==='
 */
fun <E> List<E>.removeStrict(element: E): List<E> = filter { it !== element }


